This package defines a number of other macros
besides setf that operate on generalized variables.
Many are interesting and useful even when the place is
just a variable name.
This macro is to
setfwhatpsetqis tosetq: When several places and forms are involved, the assignments take place in parallel rather than sequentially. Specifically, all subforms are evaluated from left to right, then all the assignments are done (in an undefined order).
This macro increments the number stored in place by one, or by x if specified. The incremented value is returned. For example,
(incf i)is equivalent to(setq i (1+ i)), and(incf (car x) 2)is equivalent to(setcar x (+ (car x) 2)).Once again, care is taken to preserve the “apparent” order of evaluation. For example,
(incf (aref vec (incf i)))appears to increment
ionce, then increment the element ofvecaddressed byi; this is indeed exactly what it does, which means the above form is not equivalent to the “obvious” expansion,(setf (aref vec (incf i)) (1+ (aref vec (incf i)))) ; Wrong!but rather to something more like
(let ((temp (incf i))) (setf (aref vec temp) (1+ (aref vec temp))))Again, all of this is taken care of automatically by
incfand the other generalized-variable macros.As a more Emacs-specific example of
incf, the expression(incf (point)n)is essentially equivalent to(forward-charn).
This macro decrements the number stored in place by one, or by x if specified.
This macro removes and returns the first element of the list stored in place. It is analogous to
(prog1 (carplace) (setfplace(cdrplace))), except that it takes care to evaluate all subforms only once.
This macro inserts x at the front of the list stored in place. It is analogous to
(setfplace(consx place)), except for evaluation of the subforms.
This macro inserts x at the front of the list stored in place, but only if x was not
eqlto any existing element of the list. The optional keyword arguments are interpreted in the same way as foradjoin. See Lists as Sets.
This macro shifts the places left by one, shifting in the value of newvalue (which may be any Lisp expression, not just a generalized variable), and returning the value shifted out of the first place. Thus,
(shiftfa b c d)is equivalent to(prog1 a (psetf a b b c c d))except that the subforms of a, b, and c are actually evaluated only once each and in the apparent order.
This macro rotates the places left by one in circular fashion. Thus,
(rotatefa b c d)is equivalent to(psetf a b b c c d d a)except for the evaluation of subforms.
rotatefalways returnsnil. Note that(rotatefa b)conveniently exchanges a and b.
The following macros were invented for this package; they have no analogues in Common Lisp.
This macro is analogous to
let, but for generalized variables rather than just symbols. Each binding should be of the form(place value); the original contents of the places are saved, the values are stored in them, and then the body forms are executed. Afterwards, the places are set back to their original saved contents. This cleanup happens even if the forms exit irregularly due to athrowor an error.For example,
(letf (((point) (point-min)) (a 17)) ...)moves “point” in the current buffer to the beginning of the buffer, and also binds
ato 17 (as if by a normallet, sinceais just a regular variable). After the body exits,ais set back to its original value and point is moved back to its original position.Note that
letfon(point)is not quite like asave-excursion, as the latter effectively saves a marker which tracks insertions and deletions in the buffer. Actually, aletfof(point-marker)is much closer to this behavior. (pointandpoint-markerare equivalent assetfplaces; each will accept either an integer or a marker as the stored value.)Since generalized variables look like lists,
let's shorthand of using ‘foo’ for ‘(foo nil)’ as a binding would be ambiguous inletfand is not allowed.However, a binding specifier may be a one-element list ‘(place)’, which is similar to ‘(place place)’. In other words, the place is not disturbed on entry to the body, and the only effect of the
letfis to restore the original value of place afterwards. (The redundant access-and-store suggested by the(place place)example does not actually occur.)In most cases, the place must have a well-defined value on entry to the
letfform. The only exceptions are plain variables and calls tosymbol-valueandsymbol-function. If the symbol is not bound on entry, it is simply made unbound bymakunboundorfmakunboundon exit.
This macro is to
letfwhatlet*is tolet: It does the bindings in sequential rather than parallel order.
This is the “generic” modify macro. It calls function, which should be an unquoted function name, macro name, or lambda. It passes place and args as arguments, and assigns the result back to place. For example,
(incfplace n)is the same as(callf +place n). Some more examples:(callf abs my-number) (callf concat (buffer-name) "<" (int-to-string n) ">") (callf union happy-people (list joe bob) :test 'same-person)See Customizing Setf, for
define-modify-macro, a way to create even more concise notations for modify macros. Note again thatcallfis an extension to standard Common Lisp.
This macro is like
callf, except that place is the second argument of function rather than the first. For example,(pushx place)is equivalent to(callf2 consx place).
The callf and callf2 macros serve as
building blocks for other macros like incf,
pushnew, and define-modify-macro. The
letf and letf* macros are used in the
processing of symbol macros; see Macro Bindings.